# !/usr/bin/env python
# encoding: utf-8


"""
  @author: gaogao
  @file: data_analysis_view.py
  @time: 2022/6/29 15:26
  @desc:
"""
from PyQt5 import QtWidgets
from PyQt5 import sip
from PyQt5.QtGui import QStandardItemModel, QStandardItem
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QPushButton, QVBoxLayout, QTableView, QFrame, QAbstractItemView, \
    QMessageBox, QFileDialog
from gui.custom_widget.my_matrix import Matrix
import numpy as np
from gui.data_analysis.targetConditionDialog import TargetConditionWindow
from gui.data_analysis.waferConditionDialog import WaferConditionWindow
from gui.data_analysis.conditionDialog import ConditionWindow
from gui.data_analysis.histConditionDialog import HistConditionWindow
from gui.data_analysis.contourConditionDialog import ContourConditionWindow
from gui.data_analysis.waferDialog import WaferWindow
from gui.data_analysis.multipleParaDialog import MultipleParaWindow
from gui.data_analysis.binMapDialog import BinMapWindow
from gui.data_analysis.multipleCurvesDialog import MultipleCurvesWindow
from gui.data_analysis.deleteWaferInfoDialog import DeleteWaferInfoWindow
from database.entity.wafer import Wafer
from database.entity.chip import Chip
from threading import Thread
from gui.driver.var_manager import VarManager
from utils.wafer_data_util import MapResultCenter
from utils.color_util import ncolors, create_custome_palette, get_colors
from utils.log_util import loggings
from concurrent.futures import ThreadPoolExecutor, as_completed
from gui.custom_widget.infoDialog import auto_close_dialog, show_info, show_critical
from gui.custom_widget.plot_dialog import PlotDialog

widget_header_color = "QHeaderView::section{background:gray;}"
no_data_tip = "没有符合条件的数据！"
no_curve_tip = "不是曲线数据"


class DataAnalysisView(QWidget):
    def __init__(self):
        super().__init__()
        with open("./static/style_sheet/origin.qss", mode='r', encoding='utf-8') as f:
            style_sheet = f.read()
        self.setStyleSheet(style_sheet)
        self.var_manage = VarManager()
        self.chip_name = None
        self.parameter = None
        self.multi_curve_dialog = None
        self.dist_view = None
        self.wafer_view = None
        self.bin_map_view = None
        self.contour_dialog = None
        self.muiti_paras_view = None
        self.wafer_condition_view = None
        self.target_dialog = None
        self.plot_dialog = None
        self.hist_dialog = None
        self.save_folder = None
        self.delete_wafer_view = None
        self.initUI()
        self.set_btns_status(False)
        self.bind_event()

    def set_btns_status(self, state):
        self.btn_bin.setEnabled(state)
        self.btn_map.setEnabled(state)
        self.btn_target_value_in_curve.setEnabled(state)
        self.btn_hist.setEnabled(state)
        self.btn_contour_line.setEnabled(state)
        self.btn_delete_data.setEnabled(state)
        self.btn_query_multi_params.setEnabled(state)
        self.btn_multiple.setEnabled(state)

    def bind_event(self):
        # 直方图
        self.btn_hist.clicked.connect(self.show_hist_dialog)
        # bin值map图
        self.btn_bin.clicked.connect(self.show_bin_map_view)
        # map图
        self.btn_map.clicked.connect(self.show_map_view)
        # wafer信息
        self.btn_wafer_info.clicked.connect(self.show_map_info)
        # 设置存储文件夹
        self.btn_folder_info.clicked.connect(self.show_floder_info)
        # 等高线图
        self.btn_contour_line.clicked.connect(self.show_contour_dialog)
        # 多曲线图
        self.btn_multiple.clicked.connect(self.show_multiple_curve)
        # 多参数信息
        self.btn_query_multi_params.clicked.connect(self.show_multi_paras_view)
        #
        self.data_grid.pressed.connect(self.show_grid_data)
        # 删除数据
        self.btn_delete_data.clicked.connect(self.delete_wafer_info_view)
        # 根据特定值在曲线上寻找y值
        self.btn_target_value_in_curve.clicked.connect(self.show_target_value_in_curve)
        # 导出数据
        self.btn_export.clicked.connect(self.export_data)
        self.matrix.sendSignal.connect(self.show_xy_data)
        self.matrix.spotSendSignal.connect(self.show_spot_xy_data)
        self.matrix.lineInfoSignal.connect(self.show_legend)

    def show_legend(self, legend_value):
        show_info(self, f"shot_position为{legend_value}的曲线")

    def show_floder_info(self):
        file_path = QFileDialog.getExistingDirectory(self, "选择图片文件存储位置", "./", QFileDialog.ShowDirsOnly)
        if file_path:  #
            self.save_folder = file_path
        else:
            show_critical(self, "存储文件夹不能为空！")

    def delete_wafer_info(self, wafer_name):
        try:
            Chip.delete([Chip.wafer_name == wafer_name])
            Wafer.delete([Wafer.wafer_name == wafer_name])
        except Exception as e:
            loggings.error("delete_wafer_info:" + str(e))

    def delete_wafer_info_view(self):
        wafer_list = self.get_multi_data(self.get_wafer_list, None)
        if wafer_list and len(wafer_list):
            wafer_name_list = sorted(set([wafer[0] for wafer in wafer_list]))
            if self.delete_wafer_view is None:
                self.delete_wafer_view = DeleteWaferInfoWindow()
                self.delete_wafer_view.dialogSignal.connect(self.delete_wafer_info)
            self.delete_wafer_view.set_data_2_combox(wafer_name_list)
        self.delete_wafer_view.exec_()

    def show_xy_data(self, x_data, y_data):
        pass

    def show_spot_xy_data(self, x_pos, y_pos, spot_value):
        para = self.parameter.split("_")
        if para[-1] == "BW":
            para[-1] = "SSD12"
        elif para[-1] == "IL":
            para[-1] = "SDD22"
        new_para = "_".join(para)
        query_obj = self.get_verfity_parameter_curve_pool(self.get_verfity_parameter_curve, self.wafer_name,
                                                          self.chip_name, x_pos, y_pos, new_para)
        if query_obj and isinstance(eval(query_obj[0][0]), list):
            self.plot_dialog = PlotDialog()
            self.plot_dialog.set_x_y_data(self.wafer_name, f"{x_pos},{y_pos}", self.chip_name, new_para, "Frenquce",
                                          "dbm",
                                          eval(query_obj[0][0])[0], eval(query_obj[0][0])[1])
            self.plot_dialog.show()

    def show_contour_dialog(self):
        result = self.query_spot_datas()
        chip_names = sorted(set([mea_param[0] for mea_param in result]))
        if self.contour_dialog is None:
            self.contour_dialog = ContourConditionWindow()
            self.contour_dialog.dialogSignal.connect(self.show_contour_map)
            self.contour_dialog.selectedSignal.connect(self.show_contour_parameter)
        self.contour_dialog.set_chip_list_2_widget(chip_names)
        self.contour_dialog.exec_()

    def show_contour_parameter(self, chip_name):
        if chip_name and chip_name != "":
            final_chip_name = chip_name
        else:
            final_chip_name = self.contour_dialog.cbb_chip_name.currentText()
        result = self.query_specified_chip_spot_datas(final_chip_name)
        if result:
            mea_params = sorted(set([mea_param[0] for mea_param in result]))
            if mea_params:
                self.contour_dialog.set_para_2_widget(mea_params)
        else:
            auto_close_dialog(self, "result is none")

    def show_hist_dialog(self):
        result = self.query_spot_datas()
        mea_params = sorted(set([mea_param[1] for mea_param in result]))
        # chip_names = sorted(set([mea_param[0] for mea_param in result]))
        if self.hist_dialog is None:
            self.hist_dialog = HistConditionWindow()
            self.hist_dialog.dialogSignal.connect(self.show_hist_map)
            self.hist_dialog.selectedSignal.connect(self.show_selected_index)
        self.hist_dialog.set_para_2_widget(mea_params)
        # self.hist_dialog.set_chip_list_2_widget(chip_names)
        self.hist_dialog.exec_()

    def show_selected_index(self, idx):
        global data_list
        if idx == 0:
            # lot下的所有的wafer中所有chip中的参数
            result = Wafer.query([Wafer.lotID])
            params = sorted(set([mea_param[0] for mea_param in result]))
            data_list = params
        elif idx == 1:
            # 所有的wafer中所有chip中的参数
            result = Wafer.query([Wafer.wafer_name])
            params = sorted(set([mea_param[0] for mea_param in result]))
            data_list = params
        elif idx == 2:
            # 所有chip中的参数
            result = Chip.query([Chip.chip_name],
                                filter=[Chip.data_type == "Spot"])
            params = sorted(set([mea_param[0] for mea_param in result]))
            data_list = params

        self.hist_dialog.set_data_list_2_widget(data_list)

    def show_target_value_in_curve(self):
        datas = self.get_multi_data(self.get_curve_params, None)
        chip_datas = sorted(set([data[0] for data in datas]))
        if self.target_dialog is None:
            self.target_dialog = TargetConditionWindow()
            self.target_dialog.dialogSignal.connect(self.get_spec_value_in_curve)
            self.target_dialog.seletedSignal.connect(self.show_target_para)

        self.target_dialog.set_chip_data_2_combox(chip_datas)
        self.target_dialog.exec_()

    def show_target_para(self, chip_name):
        result_params = self.get_multi_data(self.get_curve_params_with_chip_name, chip_name)
        mea_params = sorted(set([mea_param[0] for mea_param in result_params]))
        if mea_params:
            self.target_dialog.set_data_2_combox(mea_params)

    def export_data(self):
        self.save_grid_data()

    def save_grid_data(self):
        pass

    def show_bin_map_view(self):
        mea_params = self.get_multi_data(self.get_spot_params, None)
        mea_params = sorted(set([mea_param[0] for mea_param in mea_params]))
        if self.bin_map_view is None:
            self.bin_map_view = BinMapWindow()
            self.bin_map_view.set_value_2_widget(mea_params)
        self.bin_map_view.exec_()

    def show_grid_data(self, value):
        try:
            data = self.model.item(value.row(), 6)
            chip_name = self.model.item(value.row(), 1).text()
            shot_position = self.model.item(value.row(), 2).text()
            chip_number = self.model.item(value.row(), 4).text()
            parameter = self.model.item(value.row(), 5).text()
            if data.text():
                if isinstance(eval(data.text()), list):
                    self.clear_graph()
                    data = eval(data.text())
                    self.matrix.setSupTitle(
                        f"{self.lotid}-{self.vendor}-{self.wafer_name}-{shot_position}-{chip_number}-{chip_name}-{parameter}曲线")
                    is_invert_y = False
                    is_log = False
                    if "Loss_GC" in parameter or "PV" in parameter or "pλ" in parameter or "Pλ" in parameter:
                        is_invert_y = True
                    elif "MPD_I_dark" in parameter or "PDdarkcurrent" in parameter:
                        is_log = True
                    self.matrix.plot_curve(data[0], data[1], is_invert_y=is_invert_y, is_log=is_log)
                else:
                    auto_close_dialog(self, no_curve_tip)
            else:
                auto_close_dialog(self, no_data_tip)
        except Exception as e:
            loggings.error("show_grid_data:" + str(e))

    def clear_graph(self):
        self.matrix.clear()
        self.matrix.show_spines()
        self.matrix.show_grid()

    def show_map_view(self):
        if self.wafer_condition_view is None:
            self.wafer_condition_view = WaferConditionWindow()
            self.wafer_condition_view.dialogSignal.connect(self.show_specified_parameter_map)
            self.wafer_condition_view.selectedSignal.connect(self.show_chip_parameter)
        # self.wafer_condition_view.set_para_2_widget(mea_params)

        result = self.query_spot_datas()
        chip_names = sorted(set([mea_param[0] for mea_param in result]))
        self.wafer_condition_view.set_chip_list_2_widget(chip_names)
        self.wafer_condition_view.exec_()

    def show_chip_parameter(self, chip_name):
        if chip_name and chip_name != "":
            final_chip_name = chip_name
        else:
            final_chip_name = self.wafer_condition_view.cbb_chip_name.currentText()
        result = self.query_specified_chip_spot_datas(final_chip_name)
        if result:
            mea_params = sorted(set([mea_param[0] for mea_param in result]))
            self.wafer_condition_view.set_para_2_widget(mea_params)

    def show_multiple_curve(self):
        if self.multi_curve_dialog is None:
            self.multi_curve_dialog = MultipleCurvesWindow()
            self.multi_curve_dialog.dialogSignal.connect(self.curve_summary_map)
            self.multi_curve_dialog.selectedSignal.connect(self.multi_set_meas)
        # self.multi_curve_dialog.set_para_2_widget(mea_params)

        result_params = self.get_multi_data(self.get_curve_params, None)
        if result_params:
            chip_names = sorted(set([mea_param[0] for mea_param in result_params]))
            self.multi_curve_dialog.set_chip_list_2_widget(chip_names)
        else:
            auto_close_dialog(self, "没有可用的数据！")

        # self.multi_curve_dialog.set_shot_position_list_2_widget(shot_list)
        self.multi_curve_dialog.exec_()

    def multi_set_meas(self, chip_name):
        if chip_name:
            final_chip_name = chip_name
        else:
            final_chip_name = self.multi_curve_dialog.cbb_chip_name.currentText()

        result_params = self.get_multi_data(self.get_curve_params_with_chip_name, final_chip_name)
        if result_params:
            mea_params = sorted(set([mea_param[0] for mea_param in result_params]))
            if mea_params:
                self.multi_curve_dialog.set_para_2_widget(mea_params)

    def query_spot_datas(self):
        result = self.get_multi_data(self.get_spot_params, None)
        return result

    def query_specified_chip_spot_datas(self, chip_name):
        result = self.get_multi_data(self.get_chip_spot_params, chip_name)
        return result

    def show_specified_parameter_map(self, parameter, chip_name):
        data = self.use_thread_pool(self.get_spot_datas, chip_name, parameter)
        if data:
            die_list = [eval(i.shot_position) for i in data]
            pos_data_dict = {str(eval(i.shot_position)): i.measurement_data for i in data}
            pos_id_dict = {str(eval(i.shot_position)): i.shot_number for i in data}
            value_list, id_list, pos_x, pos_y, pos_broken_list = self.get_handle_map_data(
                self.handle_map_result, pos_data_dict, pos_id_dict, die_list)

            color_list = get_colors(lut=len(die_list))
            if len(value_list) > 1:
                self.chip_name = chip_name
                self.parameter = parameter
                self.matrix.setSupTitle(
                    f"{self.lotid}-{self.vendor}-{self.wafer_name}-{chip_name}-{parameter} map图")
                self.matrix.plot(value_list, color_list, value_list, pos_x, pos_y, pos_broken_list, is_show_digit=2)
                if self.save_folder:
                    image_path = f"{self.save_folder}/{parameter}map图.png"
                    self.save_image(image_path)
            else:
                auto_close_dialog(self, "数据的数量不足！")
        else:
            auto_close_dialog(self, no_data_tip)

    def save_image(self, image_path):
        self.save_graph_thread = Thread(target=self.save_graph, args=(image_path,))
        self.save_graph_thread.start()

    def save_graph(self, image_path):
        self.matrix.saveImage(image_path)

    def show_map_info(self):
        wafer_list = self.get_multi_data(self.get_wafer_list, None)
        if wafer_list and len(wafer_list):
            wafer_name_list = sorted(set([wafer[0] for wafer in wafer_list]))
            if self.wafer_view is None:
                self.wafer_view = WaferWindow()
                self.wafer_view.dialogSignal.connect(self.show_wafer_chip_data)
            self.wafer_view.set_data_2_combox(wafer_name_list)
            self.wafer_view.exec_()
        else:
            auto_close_dialog(self, "还没有数据！")

    def get_wafer_list(self):
        wafer_list = Wafer.query([Wafer.wafer_name])
        if wafer_list:
            return wafer_list

    def get_wafer_info_by_wafer_name(self, wafer_name):
        lot_vendor_info = Wafer.query([Wafer.lotID, Wafer.vendor, Wafer.create_time],
                                      filter=[Wafer.wafer_name == wafer_name])
        if lot_vendor_info:
            self.lotid = lot_vendor_info[0][0]
            self.vendor = lot_vendor_info[0][1]
            self.create_time = lot_vendor_info[0][2]

    def get_spot_params(self):
        result = Chip.query([Chip.chip_name, Chip.measurement_parameter],
                            filter=[Chip.data_type == "Spot", Chip.wafer_name == self.wafer_name])
        if result:
            return result

    def get_chip_spot_params(self, chip_name):
        result = Chip.query([Chip.measurement_parameter],
                            filter=[Chip.data_type == "Spot", Chip.chip_name == chip_name])
        if result:
            return result

    def get_curve_params(self):
        result_params = Chip.query([Chip.chip_name, Chip.measurement_parameter, Chip.shot_position],
                                   filter=[Chip.data_type == "Curve", Chip.wafer_name == self.wafer_name])
        if result_params:
            return result_params

    def get_curve_params_with_chip_name(self, chip_name):
        result_params = Chip.query([Chip.measurement_parameter, Chip.shot_position],
                                   filter=[Chip.data_type == "Curve", Chip.wafer_name == self.wafer_name,
                                           Chip.chip_name == chip_name])
        if result_params:
            return result_params

    def get_chip_list(self, wafer_name):
        chip_list = Wafer.query([Chip], filter=[Wafer.wafer_name == wafer_name, Wafer.wafer_name == Chip.wafer_name])
        return chip_list

    def show_wafer_chip_data(self, wafer_name):
        self.wafer_name = wafer_name
        self.get_wafer_info_by_wafer_name(wafer_name)
        chip_list = self.get_multi_data(self.get_chip_list, wafer_name)
        if chip_list:
            self.set_btns_status(True)
            self.show_data(chip_list)
        else:
            auto_close_dialog(self, "没有可用的数据！")

    def show_data(self, chip_list):
        try:
            self.model.removeRows(0, self.model.rowCount())
            for i in range(len(chip_list)):
                # 设置每个位置的文本值
                self.model.setItem(i, 0, QStandardItem(chip_list[i].wafer_name))
                item1 = QStandardItem(chip_list[i].chip_name)
                self.model.setItem(i, 1, item1)
                item2 = QStandardItem(chip_list[i].shot_position)
                self.model.setItem(i, 2, item2)
                item3 = QStandardItem(chip_list[i].shot_number)
                self.model.setItem(i, 3, item3)
                item4 = QStandardItem(chip_list[i].chip_number)
                self.model.setItem(i, 4, item4)
                item5 = QStandardItem(str(chip_list[i].measurement_parameter))
                self.model.setItem(i, 5, item5)
                item6 = QStandardItem(str(chip_list[i].measurement_data))
                self.model.setItem(i, 6, item6)
                item7 = QStandardItem(str(chip_list[i].data_type))
                self.model.setItem(i, 7, item7)
            self.data_grid.setModel(self.model)
        except Exception as e:
            loggings.error("update_grid:" + str(e))

    def get_spec_value_in_curve(self, chip_name, curve_name="reference_Loss", spec_value="1330"):
        try:
            if spec_value and curve_name and chip_name:
                data = self.use_thread_pool(self.get_like_data, chip_name, curve_name)
                if data:
                    curve_list = [eval(i.measurement_data) for i in data]
                    y_data = [curve[1][curve[0].index(float(spec_value))] for curve in curve_list]
                    die_list = [eval(i.shot_position) for i in data]
                    pos_data_dict = {str(eval(data[i].shot_position)): y_data[i] for i in range(len(data))}
                    pos_id_dict = {str(eval(i.shot_position)): i.shot_number for i in data}
                    value_list, id_list, pos_x, pos_y, pos_broken_list = self.get_handle_map_data(
                        self.handle_map_result, pos_data_dict, pos_id_dict, die_list)

                    color_list = get_colors(lut=len(die_list))
                    self.matrix.setSupTitle(f"{self.lotid}-{self.vendor}-{self.wafer_name}-{chip_name}-{curve_name} map图")
                    self.matrix.plot(value_list, color_list, value_list, pos_x, pos_y, pos_broken_list, is_show_digit=2)
                    if self.save_folder:
                        image_path = f"{self.save_folder}/{curve_name}-{spec_value}.png"
                        self.save_image(image_path)
                else:
                    auto_close_dialog(self, "没有找到符合条件的数据！")
        except Exception as e:
            loggings.error("get_spec_value_in_curve" + str(e))
            auto_close_dialog(self, "没有找到符合条件的数据！")

    def show_multi_paras_view(self):
        mea_params = self.get_multi_data(self.get_params, None)
        if mea_params:
            params = sorted(set([mea_param[0] for mea_param in mea_params]))
            if self.muiti_paras_view is None:
                self.muiti_paras_view = MultipleParaWindow()
                self.muiti_paras_view.dialogSignal.connect(self.update_multipara)
            self.muiti_paras_view.set_value_2_widget(params)
            self.muiti_paras_view.exec_()
        else:
            auto_close_dialog(self, "没有数据！")

    def get_params(self):
        mea_params = Chip.query([Chip.measurement_parameter], filter=[Chip.wafer_name == self.wafer_name])
        return mea_params

    # def get_spot_params(self):
    #     mea_params = Chip.query([Chip.measurement_parameter], filter=[Chip.wafer_name == self.wafer_name,Chip.data_type=="Spot"])
    #     return mea_params

    def update_multipara(self, test_paras):
        datas = []
        for test_para in test_paras:
            data = self.get_multi_data(self.get_chip_data, test_para)
            if data:
                datas.extend(data)
        if datas:
            self.show_data(datas)
            self.btn_next.setEnabled(False)
            self.btn_pre.setEnabled(False)
            self.btn_export.show()
        else:
            auto_close_dialog(self, "没有符合条件的数据！")

    def get_chip_data(self, param):
        data = Chip.query([Chip],
                          filter=[Chip.measurement_parameter == param, Chip.wafer_name == self.wafer_name])
        return data

    def get_like_data(self, chip_name, curve_name):
        data = Chip.query([Chip],
                          filter=[Chip.wafer_name == self.wafer_name,
                                  Chip.chip_name == chip_name,
                                  Chip.measurement_parameter.like(f"%{curve_name}%")])
        return data

    def get_multi_data(self, func, param):
        # try:
        with ThreadPoolExecutor(max_workers=3) as t:
            obj_list = []
            if param and param != "":
                obj = t.submit(func, param)
            else:
                obj = t.submit(func)
            obj_list.append(obj)
            for future in as_completed(obj_list):
                query_obj = future.result()
            if query_obj:
                return query_obj

    # except Exception as e:
    #     loggings.error("get_multi_data" + str(e))

    def show_contour_map(self, parameter, chip_name):
        try:
            datas = self.use_thread_pool(self.get_spot_datas, chip_name, parameter)
            if datas:
                die_list = [eval(i.shot_position) for i in datas]
                pos_data_dict = {str(eval(i.shot_position)): i.measurement_data for i in datas}
                pos_id_dict = {str(eval(i.shot_position)): i.shot_number for i in datas}
                value_list, id_list, pos_x, pos_y, pos_broken_list = self.get_handle_map_data(self.handle_map_result,
                                                                                              pos_data_dict,
                                                                                              pos_id_dict,
                                                                                              die_list)
                xlist = [eval(data.shot_position)[0] for data in datas]
                ylist = [eval(data.shot_position)[1] for data in datas]
                z_list = [float(data.measurement_data) for data in datas]
                if len(xlist) > 2:
                    self.matrix.setSupTitle(
                        f"{self.lotid}-{self.vendor}-{self.wafer_name}-{chip_name}-{parameter} 等高线图")
                    self.matrix.plot_contour(xlist, ylist, z_list)
                    if self.save_folder:
                        image_path = f"{self.save_folder}/{chip_name}-{parameter}等高线图.png"
                        self.save_image(image_path)
                else:
                    auto_close_dialog(self, "测试数据不充足！")
            else:
                auto_close_dialog(self, no_data_tip)
        except Exception as e:
            loggings.error("show_contour_map " + str(e))
            auto_close_dialog(self, "测试数据不充足！")

    def handle_map_result(self, pos_data_dict, pos_id_dict, die_list):
        value_list, id_list, pos_x, pos_y, pos_broken_list = MapResultCenter(pos_data_dict, pos_id_dict,
                                                                             die_list)._handle_raw_data()
        return value_list, id_list, pos_x, pos_y, pos_broken_list

    def get_handle_map_data(self, func, pos_data_dict, pos_id_dict, die_list):
        try:
            with ThreadPoolExecutor(max_workers=3) as t:
                obj_list = []
                obj = t.submit(func, pos_data_dict, pos_id_dict, die_list)
                obj_list.append(obj)
                for future in as_completed(obj_list):
                    query_obj = future.result()
                if query_obj:
                    return query_obj
        except Exception as e:
            loggings.error("get_handle_map_data" + str(e))

    def show_hist_map(self, data_type, parameter, data_list):
        try:
            self.matrix.clear()
            if data_type == "Lot":
                for name in data_list:
                    datas = self.use_thread_pool(self.get_spot_datas_by_lot_name, name, parameter)
                    self.canvas_hist(parameter, datas, name)

            elif data_type == "Wafer":
                for name in data_list:
                    datas = self.use_thread_pool(self.get_spot_datas_by_wafer_name, name, parameter)
                    self.canvas_hist(parameter, datas, name)

            else:
                for name in data_list:
                    datas = self.use_thread_pool(self.get_spot_datas_by_chip_name, name, parameter)
                    self.canvas_hist(parameter, datas, name)

            if self.save_folder:
                image_path = f"{self.save_folder}/{parameter}直方图.png"
                self.save_image(image_path)
        except Exception as e:
            loggings.error("show_hist_map " + str(e))

    def canvas_hist(self, parameter, total_data, label):
        try:
            if total_data:
                x_value = [round(float(data.measurement_data), 4) for data in total_data]
                x_value = np.array(sorted(x_value), dtype=object)
                self.matrix.plot_hit(x_value, parameter, label)
            else:
                auto_close_dialog(self, no_data_tip)
        except Exception as e:
            loggings.error("canvas_hist: " + str(e))

    def use_thread_pool(self, func, chip_name, parameter):
        try:
            with ThreadPoolExecutor(max_workers=3) as t:
                obj_list = []
                obj = t.submit(func, chip_name, parameter)
                obj_list.append(obj)
                for future in as_completed(obj_list):
                    query_obj = future.result()
                if query_obj:
                    return query_obj
        except Exception as e:
            loggings.error("use_thread_pool" + str(e))

    def get_verfity_curve_pool(self, func, chip_name, parameter):
        try:
            with ThreadPoolExecutor(max_workers=3) as t:
                obj_list = []
                obj = t.submit(func, chip_name, parameter)
                obj_list.append(obj)
                for future in as_completed(obj_list):
                    query_obj = future.result()
                if query_obj:
                    return query_obj
        except Exception as e:
            loggings.error("use_thread_pool" + str(e))

    def curve_summary_map(self, parameter, chip_name):
        try:
            self.clear_graph()
            query_obj = self.get_verfity_curve_pool(self.get_all_curve, chip_name, parameter)
            color_list = ncolors(len(query_obj))
            self.matrix.set_colors(color_list)
            if len(query_obj):
                self.matrix.setSupTitle(
                    f"{self.lotid}-{self.vendor}-{self.wafer_name}-{chip_name}-{parameter} 曲线对比图")
                is_invert_y = False
                is_log = False
                if "Loss_GC" in parameter or "PV" in parameter or "pλ" in parameter or "Pλ" in parameter:
                    is_invert_y = True
                elif "MPD_I_dark" in parameter or "PDdarkcurrent" in parameter:
                    is_log = True
                for j in query_obj:
                    self.matrix.plot_curve(eval(j[2])[0], eval(j[2])[1], label=f"{eval(j[0])[0]}-{eval(j[0])[1]}",
                                           is_invert_y=is_invert_y, is_log=is_log)
                    is_invert_y = False
                    is_log = False
                if self.save_folder:
                    image_path = f"{self.save_folder}/{chip_name}-{parameter}曲线对比图.png"
                    self.save_image(image_path)
            else:
                auto_close_dialog(self, no_data_tip)

        except ValueError as e:
            loggings.error("show_multiple_curves:ValueError" + str(e))
            auto_close_dialog(self, no_data_tip)
        except Exception as e:
            loggings.error("show_multiple_curves:" + str(e))
            auto_close_dialog(self, no_data_tip)

    def get_verfity_parameter_curve_pool(self, func, wafer_name, chip_name, pos_x, pos_y, curve_parameter):
        try:
            with ThreadPoolExecutor(max_workers=3) as t:
                obj_list = []
                obj = t.submit(func, wafer_name, chip_name, pos_x, pos_y, curve_parameter)
                obj_list.append(obj)
                for future in as_completed(obj_list):
                    query_obj = future.result()
                if query_obj:
                    return query_obj
        except Exception as e:
            loggings.error("use_thread_pool" + str(e))

    def get_verfity_parameter_curve(self, wafer_name, chip_name, pos_x, pos_y, curve_parameter):
        query_obj = Chip.query(Chip.measurement_data,
                               filter=[Chip.chip_name == chip_name,
                                       Chip.shot_position == f"{pos_x},{pos_y}",
                                       Chip.wafer_name == wafer_name,
                                       Chip.measurement_parameter == curve_parameter])
        return query_obj

    def get_all_curve(self, chip_name, parameter):
        query_obj = Chip.query([Chip.shot_position, Chip.shot_number, Chip.measurement_data],
                               filter=[Chip.chip_name == chip_name,
                                       Chip.measurement_parameter == parameter,
                                       Chip.wafer_name == self.wafer_name])
        return query_obj

    def get_spot_datas(self, chip_name, parameter):
        datas = Chip.query([Chip], filter=[Chip.chip_name == chip_name, Chip.measurement_parameter == parameter,
                                           Chip.wafer_name == self.wafer_name])
        return datas

    def get_spot_datas_by_chip_name(self, chip_name, parameter):
        try:
            datas = Chip.query([Chip], filter=[Chip.chip_name == chip_name, Chip.measurement_parameter == parameter])
            return datas
        except Exception as e:
            loggings.error("get_spot_datas_by_chip_name:" + str(e))

    def get_spot_datas_by_lot_name(self, lot_name, parameter):
        try:
            datas = Chip.join(Wafer, Wafer.lotID == lot_name, Chip.measurement_parameter == parameter)
            return datas
        except Exception as e:
            loggings.error("get_spot_datas_by_lot_name:" + str(e))

    def get_spot_datas_by_wafer_name(self, wafer_name, parameter):
        try:
            datas = Chip.join(Wafer, Chip.wafer_name == wafer_name, Chip.measurement_parameter == parameter)
            return datas
        except Exception as e:
            loggings.error("get_spot_datas_by_wafer_name:" + str(e))

    def initUI(self):
        self.setWindowTitle("数据分析页面")
        self.showMaximized()
        self.mainhboxLayout = QHBoxLayout(self)
        self.frame = QFrame(self)
        self.mainhboxLayout.addWidget(self.frame)
        self.vboxLayout = QVBoxLayout(self.frame)

        self.hl_btn = QHBoxLayout()
        self.hboxLayout = QHBoxLayout()

        self.btn_wafer_info = QPushButton(self.frame)
        self.btn_wafer_info.setText("wafer信息")

        self.btn_folder_info = QPushButton(self.frame)
        self.btn_folder_info.setText("设置存储文件夹")

        self.btn_bin = QPushButton(self.frame)
        self.btn_bin.setText("bin值map图")

        self.btn_map = QPushButton(self.frame)
        self.btn_map.setText("单点数据map图")

        self.btn_target_value_in_curve = QPushButton(self.frame)
        self.btn_target_value_in_curve.setText("曲线上特定值的map图")

        self.btn_hist = QPushButton(self.frame)
        self.btn_hist.setText("直方图")

        self.btn_contour_line = QPushButton(self.frame)
        self.btn_contour_line.setText("等高线图")

        self.btn_multiple = QPushButton(self.frame)
        self.btn_multiple.setText("多曲线对比图")

        self.btn_query_multi_params = QPushButton(self.frame)
        self.btn_query_multi_params.setText("查询参数值")

        self.btn_delete_data = QPushButton(self.frame)
        self.btn_delete_data.setText("删除数据")

        self.matrix = Matrix(self.frame)

        self.vl_data_page = QVBoxLayout()
        self.data_grid = QTableView(self.frame)
        self.data_grid.setEditTriggers(QAbstractItemView.NoEditTriggers)
        # 设置数据层次结构，4行4列
        self.model = QStandardItemModel(4, 8)
        # 设置水平方向四个头标签文本内容
        self.model.setHorizontalHeaderLabels(
            ['wafer name', 'chip name', 'shot position', 'shot number', 'chip number', 'measurement parameter',
             "measurement data", 'data type'])
        self.data_grid.horizontalHeader().setStyleSheet(widget_header_color)
        self.vl_data_page.addWidget(self.data_grid)
        self.hl_page_turn = QHBoxLayout()

        self.btn_pre = QPushButton(self.frame)
        self.btn_pre.setText("前一页")

        self.btn_next = QPushButton(self.frame)
        self.btn_next.setText("后一页")

        self.btn_export = QPushButton(self.frame)
        self.btn_export.setText("导出数据")
        self.btn_export.hide()
        self.hl_page_turn.addWidget(self.btn_pre)
        self.hl_page_turn.addWidget(self.btn_next)
        self.hl_page_turn.addWidget(self.btn_export)

        self.hboxLayout.addWidget(self.matrix)
        self.vl_data_page.addLayout(self.hl_page_turn)
        self.hboxLayout.addLayout(self.vl_data_page)

        # self.vboxLayout.addLayout(self.search_layout)
        self.hl_btn.addWidget(self.btn_wafer_info)
        self.hl_btn.addWidget(self.btn_folder_info)
        self.hl_btn.addWidget(self.btn_bin)
        self.hl_btn.addWidget(self.btn_map)
        self.hl_btn.addWidget(self.btn_target_value_in_curve)
        self.hl_btn.addWidget(self.btn_hist)
        self.hl_btn.addWidget(self.btn_contour_line)
        self.hl_btn.addWidget(self.btn_multiple)
        self.hl_btn.addWidget(self.btn_query_multi_params)
        self.hl_btn.addWidget(self.btn_delete_data)
        self.vboxLayout.addLayout(self.hl_btn)
        self.vboxLayout.addLayout(self.hboxLayout)
        self.setLayout(self.mainhboxLayout)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    # 数据库的路径变化
    myWindow = DataAnalysisView()
    myWindow.show()
    sys.exit(app.exec_())
